package cn.chengpengper.seckill.activity.application.service.impl;

import cn.chengpengper.seckill.activity.application.builder.SeckillActivityBuilder;
import cn.chengpengper.seckill.activity.application.cache.service.SeckillActivityCacheService;
import cn.chengpengper.seckill.activity.application.cache.service.SeckillActivityListCacheService;
import cn.chengpengper.seckill.activity.application.service.SeckillActivityService;
import cn.chengpengper.seckill.activity.domain.model.entity.SeckillActivity;
import cn.chengpengper.seckill.activity.domain.service.SeckillActivityDomainService;
import cn.chengpengper.seckill.common.cache.model.SeckillBusinessCache;
import cn.chengpengper.seckill.common.code.HttpCode;
import cn.chengpengper.seckill.common.exception.SeckillException;
import cn.chengpengper.seckill.common.model.dto.SeckillActivityDTO;
import cn.chengpengper.seckill.common.model.enums.SeckillActivityStatus;
import cn.chengpengper.seckill.common.utils.bean.BeanUtil;
import cn.chengpengper.seckill.common.utils.id.SnowFlakeFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author chengpeng.hu
 */
@Service
@RequiredArgsConstructor
public class SeckillActivityServiceImpl implements SeckillActivityService {

    private final SeckillActivityListCacheService seckillActivityListCacheService;

    private final SeckillActivityCacheService seckillActivityCacheService;

    private final SeckillActivityDomainService seckillActivityDomainService;

    @Override
    public void saveSeckillActivity(SeckillActivityDTO seckillActivityDTO) {
        if (Objects.isNull(seckillActivityDTO)) {
            throw new SeckillException(HttpCode.PARAMS_INVALID);
        }
        SeckillActivity seckillActivity = new SeckillActivity();
        BeanUtil.copyProperties(seckillActivityDTO, seckillActivity);
        seckillActivity.setId(SnowFlakeFactory.getSnowFlakeFromCache().nextId());
        seckillActivity.setStatus(SeckillActivityStatus.PUBLISHED.getCode());
        seckillActivityDomainService.saveSeckillActivity(seckillActivity);
    }

    @Override
    public List<SeckillActivity> getSeckillActivityList(Integer status) {
        return seckillActivityDomainService.getSeckillActivityList(status);
    }

    @Override
    public List<SeckillActivity> getSeckillActivityBetweenStartTimeAndEndTime(Date currentTime, Integer status) {
        return seckillActivityDomainService.getSeckillActivityBetweenStartTimeAndEndTime(currentTime, status);
    }

    @Override
    public SeckillActivity getSeckillActivityById(Long id) {
        return seckillActivityDomainService.getSeckillActivityById(id);
    }

    @Override
    public void updateStatus(Integer status, Long id) {
        seckillActivityDomainService.updateStatus(status, id);
    }

    @Override
    public List<SeckillActivityDTO> getSeckillActivityList(Integer status, Long version) {
        SeckillBusinessCache<List<SeckillActivity>> seckillActivityListCache = seckillActivityListCacheService.getCachedActivities(status, version);
        if (!seckillActivityListCache.isExist()) {
            throw new SeckillException(HttpCode.ACTIVITY_NOT_EXISTS);
        }
        // 稍后再试，前端需要对这个状态做特殊处理，即不去刷新数据，静默稍后再试
        if (seckillActivityListCache.isRetryLater()) {
            throw new SeckillException(HttpCode.RETRY_LATER);
        }
        return seckillActivityListCache.getData().stream().map((seckillActivity) -> {
            SeckillActivityDTO seckillActivityDTO = new SeckillActivityDTO();
            BeanUtil.copyProperties(seckillActivity, seckillActivityDTO);
            seckillActivityDTO.setVersion(seckillActivityListCache.getVersion());
            return seckillActivityDTO;
        }).collect(Collectors.toList());
    }

    @Override
    public SeckillActivityDTO getSeckillActivity(Long id, Long version) {
        SeckillBusinessCache<SeckillActivity> cachedSeckillActivity = seckillActivityCacheService.getCachedSeckillActivity(id, version);
        if (!cachedSeckillActivity.isExist()) {
            throw new SeckillException(HttpCode.ACTIVITY_NOT_EXISTS);
        }
        // 稍后再试，前端需要对这个状态做特殊处理，即不去刷新数据，静默稍后再试
        if (cachedSeckillActivity.isRetryLater()) {
            throw new SeckillException(HttpCode.RETRY_LATER);
        }
        SeckillActivityDTO seckillActivityDTO = SeckillActivityBuilder.toSeckillActivityDTO(cachedSeckillActivity.getData());
        seckillActivityDTO.setVersion(cachedSeckillActivity.getVersion());
        return seckillActivityDTO;
    }
}
